﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TiposComuns.Objectos;

namespace Pesquisa
{
    /// <summary>
    /// Contains a map between the hash of a searched property,
    /// and the list of people that have it, to a maximum value.
    /// It also contains the information required to continue this list.
    /// </summary>
    public class SearchedNodes
    {
        #region Consts
        public const int MAX = 10;
        #endregion

        #region Attributes
        private Dictionary<byte[], List<Person>> map = 
            new Dictionary<byte[], List<Person>>();//Mapping between propertie and persons that have it
        private byte[] contKey;                     /*Continuation key - Indicates the k next nodes that
                                                     * holds more people with this property.
                                                     * */
        private KClosest nexts;                 //Temporarily holds the person that are closest to contKey
        #endregion

        #region Methods
        /// <summary>
        /// Adds a new entry to the list of nodes
        /// </summary>
        /// <param name="key">Key of the property</param>
        /// <param name="person">New person</param>
        /// <returns>True if the list wasn't full, false otherwise</returns>
        public bool Add(byte[] key, Person person)
        {
            List<Person> list = this.map[key];
            if (list==null)
            {
                list = new List<Person>(SearchedNodes.MAX);
                this.map.Add(key, list);
            }
            if (list.Count == SearchedNodes.MAX)
                return false;
            list.Add(person);

            return true;
        }

        /// <summary>
        /// Tries to remove a person from the map.
        /// If it doesn't contain it, returns the rest
        /// of the global map.
        /// </summary>
        /// <param name="key">Property's key</param>
        /// <param name="person">Person to remove</param>
        /// <returns>Null, if it could remove it, or a pair composed of the
        /// key and list of person that might store the person to remove</returns>
        public KeyValuePair<byte[], KClosest> Remove(byte []key,Person person)
        {
            List<Person> list = this.map[key];
            if (list == null || !list.Remove(person)) return new KeyValuePair<byte[],KClosest>();

            return new KeyValuePair<byte[], KClosest>(contKey, nexts);
        }


        /// <summary>
        /// Sets the metadata related to the continuation of
        /// the distributed map.
        /// </summary>
        /// <param name="contKey">Continuation key</param>
        /// <param name="nexts">K closest nodes to contKey</param>
        public void SetNexts(byte []contKey, KClosest nexts)
        {
            this.contKey = contKey;
            this.nexts = nexts;
        }

        #endregion
    }
}
